﻿using ajayumi.develop.win32.Transport.WCF.Services;
using ajayumi.develop.win32.Transport.WCF.Services.DataContracts;
using System;
using System.IO;
using System.ServiceModel;

namespace ajayumi.develop.win32.Transport.Core
{
    /// <summary>
    /// 上传文件
    /// Author  : 黄乙冬
    /// Date    : 2011-08-29
    /// </summary>
    public class UploadFile : TransFileBase
    {
        public Func<int> GetBufferSize { get; set; }

        protected Func<TransFileInfo, TransFileInfo> InvokeInitUploadFile { get; private set; }

        protected Func<TransFileInfo, TransFileInfo> InvokeUploadFile { get; private set; }


        public UploadFile(string rootPath, string relativePath,
            Func<TransFileInfo, TransFileInfo> initUploadFileFunc,
            Func<TransFileInfo, TransFileInfo> uploadFileFunc)
            : base(rootPath, relativePath, TransportAction.Upload)
        {
            this.InvokeInitUploadFile = initUploadFileFunc;
            this.InvokeUploadFile = uploadFileFunc;
        }

        protected UploadFile(string rootPath, string relativePath, TransportAction action,
            Func<TransFileInfo, TransFileInfo> initUploadFileFunc,
            Func<TransFileInfo, TransFileInfo> uploadFileFunc)
            : base(rootPath, relativePath, action)
        {
            this.InvokeInitUploadFile = initUploadFileFunc;
            this.InvokeUploadFile = uploadFileFunc;
        }

        protected override void BeginTransFileTask()
        {
            FileInfo fileInfo = new FileInfo(this.FilePath);
            string fileName = fileInfo.Name;
            long length = fileInfo.Length;
            int progressPercentage = 0;
            int maxSize = 1024; //每次上传的数据块大小(Byte)
            if (this.GetBufferSize != null)
            { maxSize *= this.GetBufferSize(); }

            try
            {
                TransFileInfo transFileInfo = this.InvokeInitUploadFile(
                    new TransFileInfo()
                    {
                        Name = fileName,
                        RelativePath = this.RelativePath,
                        Length = length,
                        TransportAction = this.TransportAction
                    });

                if (length > 0)
                {
                    progressPercentage = Convert.ToInt32(Convert.ToSingle(transFileInfo.Offset) / Convert.ToSingle(length) * 100f);
                }
                this.OnTransReady(new TransReadyEventArgs(this.TransportAction, "", this.RelativePath, length, progressPercentage));

                if (transFileInfo.Offset == length)
                {
                    this.OnTransCompleted(new TransCompletedEventArgs(this.TransportAction,
                        this.RelativePath, string.Empty, DateTime.Now,
                        null, false, this));
                    return;
                }

                using (FileStream stream = File.Open(this.FilePath, FileMode.Open, FileAccess.Read))
                {
                    while (transFileInfo.Offset != length)
                    {
                        //分块上传文件
                        long bufferLength = length - transFileInfo.Offset >= maxSize ? maxSize : length - transFileInfo.Offset;
                        transFileInfo.Data = new byte[bufferLength];

                        stream.Position = transFileInfo.Offset;
                        stream.Read(transFileInfo.Data, 0, transFileInfo.Data.Length);
                        transFileInfo = this.InvokeUploadFile(transFileInfo);

                        //报告进度
                        progressPercentage = Convert.ToInt32(Convert.ToSingle(transFileInfo.Offset) / Convert.ToSingle(length) * 100f);
                        this.OnTransProgressChanged(new TransProgressChangedEventArgs(this.TransportAction, this.RelativePath, progressPercentage, this));
                    }
                }

                this.OnTransCompleted(new TransCompletedEventArgs(this.TransportAction,
                    this.RelativePath, string.Empty, DateTime.Now,
                    null, false, this));
            }
            catch (FaultException ex)
            {
                this.OnTransCompleted(new TransCompletedEventArgs(this.TransportAction,
                    this.RelativePath, string.Empty, DateTime.Now,
                    ex, true, this));
            }
            catch (TimeoutException ex)
            {
                this.OnTransCompleted(new TransCompletedEventArgs(this.TransportAction,
                    this.RelativePath, string.Empty, DateTime.Now,
                    ex, true, this));
            }
            catch (Exception ex)
            {
                this.OnTransCompleted(new TransCompletedEventArgs(this.TransportAction,
                    this.RelativePath, string.Empty, DateTime.Now,
                    ex, true, this));
            }

        }



    }
}
